home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Arsenal Files 8
/
The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO
/
g_quake
/
server~1.zip
/
_DRONE.QC
< prev
next >
Wrap
Text File
|
1996-10-04
|
18KB
|
601 lines
/*
**
** _drone.qc (Drone Code, 1.0)
**
** Copyright (C) 1996 Johannes Plass
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
** Author: Johannes Plass (plass@dipmza.physik.uni-mainz.de)
**
*/
void(entity player) DroneInfo =
{
if (!USE_MODULE_DRONE) return;
// 123456789#123456789#123456789#12345678
sprint(player,"£");
sprint(player," Drone");
sprint(player, " provides homing missiles.\n");
sprint(player," Type 'help-drone' for help.\n");
};
void(entity player) DroneInit =
{
if (!USE_MODULE_DRONE) return;
stuffcmd(player,"alias help-drone \"impulse 215\";\n");
};
void(entity player) DroneHelp =
{
if (!USE_MODULE_DRONE) return;
// 123456789#123456789#123456789#12345678
sprint(player,"Drone:");
sprint(player, " provides homing missiles.\n");
sprint(player,"To launch a drone double-select the\n");
sprint(player,"grenade launcher, then press fire.\n");
sprint(player,"The silver key is lit if the grenade\n");
sprint(player,"launcher fires drones.\n");
sprint(player,"The gold key is lit if you are\n");
sprint(player,"targeted by a drone.\n");
sprint(player,"Flying drones can be shot down.\n");
};
void(entity player) DroneActiveMessage =
{
if (!USE_MODULE_DRONE) return;
// 123456789#123456789#123456789#12345678
sprint(player," Drone (help-drone)\n");
};
//========================================================================
// DroneToggleWeapon
//========================================================================
void(entity player) DroneToggleWeapon =
{
if (!USE_MODULE_DRONE) return;
if (player.modules_weapon & MODULES_WEAPON_DRONE) {
player.modules_weapon = player.modules_weapon - MODULES_WEAPON_DRONE;
player.items = player.items - (player.items & IT_KEY1);
} else {
if ((player.weapon == IT_GRENADE_LAUNCHER) && (player.ammo_rockets >= 1)) {
player.modules_weapon = player.modules_weapon | MODULES_WEAPON_DRONE;
player.items = player.items | IT_KEY1;
}
}
};
//========================================================================
// DroneResetWeapon
//========================================================================
void(entity player) DroneResetWeapon =
{
if (!USE_MODULE_DRONE) return;
if (player.modules_weapon & MODULES_WEAPON_DRONE) {
player.modules_weapon = player.modules_weapon - MODULES_WEAPON_DRONE;
player.items = player.items - (player.items & IT_KEY1);
}
};
//========================================================================
// DroneThreat
//========================================================================
void(entity player,float threat) DroneThreat =
{
if (threat) player.items = player.items | IT_KEY2;
else player.items = player.items - (player.items & IT_KEY2);
};
//========================================================================
// DroneRemoveFromQueue
//========================================================================
void(entity player,entity drone) DroneRemoveFromQueue =
{
//dprint("DroneRemoveFromQueue\n");
if (!drone.drone_in_queue) return;
if (player.drone_1 == drone) {
player.drone_1 = world;
player.drone_count = player.drone_count - (player.drone_count & 1);
}
else if (player.drone_2 == drone) {
player.drone_2 = world;
player.drone_count = player.drone_count - (player.drone_count & 2);
}
else if (player.drone_4 == drone) {
player.drone_4 = world;
player.drone_count = player.drone_count - (player.drone_count & 4);
}
else if (player.drone_8 == drone) {
player.drone_8 = world;
player.drone_count = player.drone_count - (player.drone_count & 8);
}
drone.drone_in_queue = 0;
};
//========================================================================
// DroneAddToQueue
//========================================================================
void(entity player,entity drone) DroneAddToQueue =
{
//dprint("DroneAddToQueue\n");
if (!(player.drone_count & 1)) {
player.drone_1 = drone;
player.drone_count = player.drone_count | 1;
}
else if (!(player.drone_count & 2)) {
player.drone_2 = drone;
player.drone_count = player.drone_count | 2;
}
else if (!(player.drone_count & 4)) {
player.drone_4 = drone;
player.drone_count = player.drone_count | 4;
}
else if (!(player.drone_count & 8)) {
player.drone_8 = drone;
player.drone_count = player.drone_count | 8;
}
drone.drone_in_queue = 1;
};
//========================================================================
// DroneRemoveDrone
//========================================================================
void(entity player) DroneRemoveDrone =
{
local entity m;
local float t;
//dprint("DroneRemoveDrone\n");
if (player.drone_count & 15 != 15) return;
t = time+10;
m = world;
if (player.drone_count & 1)
{ if (player.drone_1.ltime < t) { m = player.drone_1; t = player.drone_1.ltime; }}
if (player.drone_count & 2)
{ if (player.drone_2.ltime < t) { m = player.drone_2; t = player.drone_2.ltime; }}
if (player.drone_count & 4)
{ if (player.drone_4.ltime < t) { m = player.drone_4; t = player.drone_4.ltime; }}
if (player.drone_count & 8)
{ if (player.drone_8.ltime < t) { m = player.drone_8; t = player.drone_8.ltime; }}
if (m!= world) {
//dprint("killing drone\n");
DroneRemoveFromQueue(m.drone_owner,m);
m.nextthink = time+0.01;
m.touch = SUB_Null;
m.think = DroneDie;
}
};
//========================================================================
// DroneFire
//========================================================================
void(entity drone) DroneFire =
{
//dprint("DroneFire\n");
DroneRemoveDrone(self);
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
self.punchangle_x = -2;
makevectors(self.v_angle);
drone = spawn();
drone.classname = "drone";
drone.owner = self;
drone.drone_owner = self;
drone.movetype = MOVETYPE_FLY;
drone.solid = SOLID_BBOX;
drone.velocity = aim(self,DRONE_VELOCITY_START);
drone.velocity = drone.velocity * DRONE_VELOCITY_START;
drone.origin = self.origin + v_forward*12 + '0 0 16';
drone.modules_weapon = MODULES_WEAPON_DRONE;
drone.angles = vectoangles(drone.velocity);
drone.touch = DroneTouch;
drone.ltime = time;
drone.nextthink = time + DRONE_THINK_FIRSTTIME;
drone.think = DroneThink;
drone.avelocity = '300 300 300';
drone.effects = drone.effects | EF_DIMLIGHT;
drone.health = 20;
drone.takedamage = DAMAGE_AIM;
drone.th_die = DroneDie;
drone.enemy = self;
drone.drone_target_vector = self.origin;
drone.drone_target_vector_z = drone.drone_target_vector_z + DRONE_TARGET_OFFSET_Z;
drone.drone_target_velocity = self.velocity;
drone.drone_set_target_vector_time = time - 10;
DroneFindTarget(drone);
DroneAddToQueue(self,drone);
DroneThreat(drone.enemy,TRUE);
setmodel (drone, "progs/v_spike.mdl");
setsize (drone, '0 0 0', '0 0 0');
setorigin (drone, drone.origin);
sound (self, CHAN_WEAPON, drone_launch_sound_1, 1, ATTN_NORM);
sound (drone, CHAN_WEAPON, drone_launch_sound_2, 1, ATTN_NORM);
drone.drone_sound_time = time - 0.3;
};
//========================================================================
// DroneTouch
//========================================================================
float DRONE_DAMAGE_RADIUS = 70;
void() DroneTouch =
{
local float d,db,r;
local entity e;
//dprint("DroneTouch\n");
//dprint(other.classname); dprint("\n");
if (pointcontents(self.origin) == CONTENT_SKY) {
DroneThreat(self.enemy,FALSE);
remove(self);
return;
}
if (other.solid == SOLID_BSP) {
//dprint("wall collision\n");
//dprint(vtos(self.velocity)); dprint("\n");
if (checkbottom(self)) {
//dprint("on floor\n");
if (self.drone_bounced) self.origin_z = self.origin_z + 8;
if (!self.drone_firstthink) self.nextthink = time + 0.1;
}
if (time > self.drone_bounce_sound_time + 0.6) {
//dprint("drone receives damage\n");
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 0.6, ATTN_NORM);
self.drone_bounce_sound_time = time;
self.drone_sound_time = time - 0.4;
if (self.health > 0) T_Damage (self, world, world, 3);
}
self.drone_bounce_time = time;
self.drone_bounced = 1;
setsize (self, '-0 -0 -0', '0 0 0');
return;
}
else if (other.solid == SOLID_BBOX) {
if (other.classname == "drone" && self.drone_count >= 0) {
//dprint("bounce against drone\n");
if (time > self.drone_bounce_sound_time + 0.6) {
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 0.8, ATTN_NORM);
self.drone_bounce_sound_time = time;
self.drone_sound_time = time;
if (self.health > 0) {
d = 6;
if (self.drone_owner == other.drone_owner) d = 3;
T_Damage (self, world, world, d);
}
}
return;
}
else if (other.classname == "grenade") {
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 0.6, ATTN_NORM);
self.drone_sound_time = time;
if (self.health > 0) T_Damage (self, world, world, 5);
return;
}
else if (other.classname == "spike") {
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 0.6, ATTN_NORM);
self.drone_sound_time = time;
if (self.health > 0) T_Damage (self, world, world, 6);
return;
}
}
self.think = DroneDie; // be on the
self.nextthink = time +3; // safe side
self.owner = self.drone_owner;
DroneThreat(self.enemy,FALSE);
DroneRemoveFromQueue(self.drone_owner,self);
e = findradius(self.origin, DRONE_DAMAGE_RADIUS);
while (e) {
if (e.takedamage == DAMAGE_AIM) {
if (e.health > 0) {
if (e != self) {
r = random();
db = 40 + r*5;
d = vlen(e.origin + '0 0 16' - self.origin);
if (d < DRONE_DAMAGE_RADIUS - 1.2*db) d = db;
else if (d < DRONE_DAMAGE_RADIUS) d = (DRONE_DAMAGE_RADIUS-d)*0.83;
else d = 0;
if (d > 0) {
if (e.classname == "drone") {
if (e.drone_owner == self.drone_owner) d = d*0.4;
e.health = e.health - d;
if (e.health <= 0) {
e.think = DroneDie;
e.nextthink = time + 0.01;
}
} else {
T_Damage (e, self, self.drone_owner, d);
if (r > 0.95) { //#jp#(Burn)
if (d > 20) { //#jp#(Burn)
BurnSetOnFire(e,self.drone_owner); //#jp#(Burn)
} //#jp#(Burn)
} //#jp#(Burn)
}
}
}
}
}
e = e.chain;
}
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
BecomeExplosion();
};
//========================================================================
// DroneDie
//========================================================================
void() DroneDie =
{
local entity o;
//dprint("DroneDie\n");
o = other;
other = self;
self.drone_count = -1; // needed as trigger in DroneTouch
DroneTouch();
other = o;
};
//========================================================================
// DroneThink
//========================================================================
void() DroneThink =
{
local vector x,v;
local float have,xn,tvn,vn,tvn,vwn,vmin;
//dprint("DroneThink\n");
//dprint(ftos(time)); dprint("\n");
if (time > self.drone_sound_time + 0.8) {
sound (self, CHAN_WEAPON, drone_hoover_sound, 1, ATTN_NORM);
self.drone_sound_time = time;
}
if (time > self.ltime + DRONE_LIFETIME + 0.5) {
self.touch = SUB_Null;
self.think = DroneDie;
self.nextthink = time + 0.01;
self.drone_firstthink = 1;
return;
}
if (self.drone_origin_old == self.origin) {
//dprint("didn't move\n");
self.velocity_z = 150;
self.drone_stuck = self.drone_stuck + 1;
if (self.drone_stuck >= 4) {
//dprint("stuck, proposing self destruction\n");
self.ltime = -100;
self.drone_stuck = 0;
}
}
else self.drone_stuck = 0;
if (self.flags & FL_ONGROUND) self.velocity_z = 150;
self.movetype = MOVETYPE_FLY;
self.think = DroneThink;
self.nextthink = time + DRONE_THINK_NEXTTIME;
self.drone_origin_old = self.origin;
self.flags = self.flags - (self.flags & FL_ONGROUND);
if (self.drone_bounced) {
if (time >= self.drone_bounce_time + 0.2) {
//dprint("resetting size after bouncing\n");
setsize (self, '-8 -8 -8', '8 8 8');
self.drone_bounced = 0;
}
}
DroneThreat(self.enemy,FALSE);
if (!self.drone_firstthink) {
setsize (self, '-8 -8 -8', '8 8 8');
self.drone_firstthink = 1;
self.owner = self;
DroneFindTarget(self);
}
have = 0;
if (self.drone_target_is_fixed) {
have = 3;
}
else if (self.enemy.deadflag > DEAD_NO) {
self.drone_target_is_fixed = 1;
have = 3;
}
else if (time > self.drone_targeting_time + 2) {
if (vlen(self.drone_target_vector - self.origin) > 150) have = 1;
}
if (!have) {
if (time > self.drone_targeting_time + 1) {
if (self.enemy == self.drone_owner) have = 1;
}
if (!have) {
if (time > self.drone_set_target_vector_time + 0.5) have = 2;
}
}
if (have == 1) have = DroneFindTarget(self);
else if (have == 2) have = DroneUpdateTargetData(self.enemy,self);
if (!have) {
if (vlen(self.drone_target_vector-self.origin) < 40) have = 2;
else {
v = self.enemy.origin;
v_z = v_z + DRONE_TARGET_OFFSET_Z;
traceline(self.origin, v, TRUE, self);
if (trace_fraction == 1) have = 2;
}
if (have) {
self.drone_target_vector = self.enemy.origin;
self.drone_target_vector_z = self.drone_target_vector_z + DRONE_TARGET_OFFSET_Z;
self.drone_target_velocity = self.enemy.velocity;
}
}
DroneThreat(self.enemy,TRUE);
//dprint("target:"); dprint(self.enemy.classname); dprint(" "); dprint(self.enemy.netname); dprint("\n");
x = self.drone_target_vector - self.origin;
xn = vlen(x);
x = normalize(x);
tvn = vlen(self.drone_target_velocity);
v = normalize(self.velocity);
vn = vlen(self.velocity);
vmin = 150;
if (v*x < -0.92) {
//dprint("randomize\n");
x = self.drone_target_vector - self.origin;
x_x = x_x + 40*(0.5 - random());
x_y = x_y + 40*(0.5 - random());
x_z = x_z + 30*random();
xn = vlen(x);
x = normalize(x);
}
if (xn < 250) vwn = tvn+70+(1+v*x)*xn/500*50;
else if (xn < 500) vwn = 400;
else vwn = 600;
if (vn > vwn) { vn = vn - 100; if (vn < vmin) vn = vmin; }
else if (vn < vwn) { vn = vn + 100; if (vn > vwn) vn = vwn; }
else if (vn < vmin) { vn = vmin; }
self.velocity = self.velocity + x*vn;
if (self.velocity == '0 0 0') {
self.velocity = self.velocity + x*(vn+10);
} else {
tvn = vlen(self.velocity);
if (tvn > vn) self.velocity = vn*normalize(self.velocity);
else if (tvn < vmin) self.velocity = vmin*normalize(self.velocity);
}
};
//========================================================================
// DroneUpdateTargetData
//========================================================================
float(entity targ,entity drone) DroneUpdateTargetData =
{
local vector v;
//dprint("DroneUpdateTargetData\n");
drone.drone_set_target_vector_time = time;
v = targ.origin;
v_z = v_z + DRONE_TARGET_OFFSET_Z;
traceline(drone.origin, v, TRUE, drone);
if (trace_fraction != 1) {
v = v + '20 20 0';
traceline(drone.origin, v, TRUE, drone);
if (trace_fraction != 1) {
v = v + '-40 -40 0';
traceline(drone.origin, v, TRUE, drone);
if (trace_fraction != 1) {
v = v + '0 40 0';
traceline(drone.origin, v, TRUE, drone);
if (trace_fraction != 1) {
v = v + '40 -40 0';
traceline(drone.origin, v, TRUE, drone);
if (trace_fraction != 1) {
return(0);
}
}
}
}
}
drone.enemy = targ;
drone.drone_target_vector = v;
drone.drone_target_velocity = targ.velocity;
return(1);
};
//========================================================================
// DroneFindTarget
//========================================================================
float(entity drone) DroneFindTarget =
{
local entity e, t;
local vector m_forward;
local float cos_min,cos;
//dprint("DroneFindTarget\n");
cos_min = -10;
m_forward = normalize(drone.velocity);
e = findradius(drone.origin+1000*m_forward,1050);
while (e) {
if (e.takedamage == DAMAGE_AIM) {
if (e.health > 0) {
if (e.drone_owner != drone.drone_owner || e.classname != "drone") {
if ((drone.drone_owner.waterlevel < 3 && e.waterlevel < 3)
|| drone.drone_owner.waterlevel == e.waterlevel) {
cos = normalize(e.origin)*m_forward;
if (cos > cos_min) {
if (DroneUpdateTargetData(e,drone)) {
cos_min = cos;
}
}
}
}
}
}
e = e.chain;
}
drone.drone_targeting_time = time;
if (cos_min == -1) return(0);
else return(1);
};